﻿using System;
using System.Collections.Generic;
using System.Text;
using OL.FrameCore.Application.User.Dto;
using OL.FrameCore.Infrastructure.Utility;
using Microsoft.EntityFrameworkCore;
using OL.FrameCore.Infrastructure.UnitOfWork;
using OL.FrameCore.Domain.Entity;
using System.Linq;
using OL.FrameCore.Domain.Enum;
using System.Linq.Expressions;
using System.Transactions;
using OL.FrameCore.Application.Module.Dto;
using System.Security.Cryptography;
using OL.FrameCore.Application.Module;
using OL.FrameCore.Infrastructure.Security;

namespace OL.FrameCore.Application.User
{
    public class UserService :  IUserService
    {
        IUnitOfWork _unitOfwork;
        IModuleService _moduleService;
        public UserService(IUnitOfWork unitOfwork, IModuleService moduleService)
        {
            _unitOfwork = unitOfwork;
            _moduleService = moduleService;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public LoginResponse VerifyLogin(LoginRequest request)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var model = repositorySysUser.TableNoTracking.SingleOrDefault(p => p.UserName == request.UserName);
            if (model == null)
            {
                return new LoginResponse { Code = LoginEnum.NoUser };
            }
            int userId = model.Id;
            if (model.Status == 1)
            {
                return new LoginResponse
                {
                    Code = LoginEnum.UserDisable,
                    UserId = userId
                };
            }

            //md5加密
            string pwd = MD5Utility.MD5(request.Password);

            if (model.Password == pwd)
            {
                return new LoginResponse
                {
                    Code = LoginEnum.Success,
                    UserId = userId
                };
            }
            else
            {
                return new LoginResponse
                {
                    Code = LoginEnum.WrongPassword,
                    UserId = userId
                };
            }

        }

        /// <summary>
        /// 获取登录用户信息
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public GetLoginUserInfoResponse GetLoginUserInfo(int userId)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var model = repositorySysUser.TableNoTracking.SingleOrDefault(c => c.Id == userId);
            if (model == null)
                return null;

            return new GetLoginUserInfoResponse
            {
                UserId = model.Id,
                UserName = model.UserName,
                TrueName = model.TrueName,
                Role = ""
            };
        }

        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public GetUserResponse GetUser(int userId)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var model = repositorySysUser.TableNoTracking.Where(p=>p.Id==userId).SingleOrDefault();
            return new GetUserResponse
            {
                Id = model.Id,
                UserName = model.UserName,
                TrueName = model.TrueName,
                Sex = model.Sex,
                DeptId = model.DeptId,
                Phone = model.Phone,
                Email = model.Email
            };
        }
        /// <summary>
        /// 获取用户列表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public PageData<GetUserListResponse> GetUserList(GetUserListRequest request)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var repositorySysDept = _unitOfwork.GetRepository<SysDept>();
            var query = from a in repositorySysUser.TableNoTracking
                        join b in repositorySysDept.TableNoTracking on a.DeptId equals b.Id into tmpB
                        from b in tmpB.DefaultIfEmpty()
                        where (request.UserId <= 0 ? true : a.Id == request.UserId)
                        && (string.IsNullOrEmpty(request.UserName) ? true : a.UserName == request.UserName)
                        && (string.IsNullOrEmpty(request.TrueName) ? true : a.TrueName == request.TrueName)
                        && (request.DeptId.HasValue ? a.DeptId == request.DeptId : true)
                        && (request.Status.HasValue ? a.Status == request.Status : true)
                        && a.IsDelete == false
                        orderby a.UpdateTime descending
                        select new GetUserListResponse
                        {
                            Id = a.Id,
                            UserName = a.UserName,
                            TrueName = a.TrueName,
                            DeptName = b.DeptName ?? "--",
                            Status = a.Status,
                            Phone = a.Phone,
                            Email = a.Email,
                            CreateTime = a.CreateTime
                        };

            return repositorySysUser.PagingAsync<GetUserListResponse>(query, request.PageIndex, request.PageSize).Result;
        }

        public List<GetUserListResponse> GetUserPagetList2(GetUserListRequest request)
        {
            string sql = @"
                select a.id,a.username,b.deptname
                from sys_user a
                left join sys_dept b on a.deptid=b.id
                where a.id=1
                ";
            var list = _unitOfwork.SqlQuery<GetUserListResponse>(sql).ToList();
            return list;
        }
        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result AddUser(AddUserRequest request)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var repositoryUserOperateLog = _unitOfwork.GetRepository<SysUserOperateLog>();

            if (repositorySysUser.TableNoTracking.Any(p => p.UserName == request.UserName && p.IsDelete == false))
            {
                return new FailResult("已存在相同用户名");
            }

            var model = new SysUser
            {
                UserName = request.UserName,
                Password = request.Password,
                TrueName = request.TrueName,
                Sex = request.Sex,
                Phone = request.Phone,
                Email = request.Email,
                DeptId = request.DeptId,
                CreateId = request.OpeatorId,
                CreateTime = DateTime.Now,
                UpdateId = request.OpeatorId,
                UpdateTime = DateTime.Now,
                Status = 0,
                IsDelete = false
            };
            repositorySysUser.Insert(model);

            //日志
            repositoryUserOperateLog.Insert(new SysUserOperateLog
            {
                OperateId = request.OpeatorId,
                OperateType = 0,
                UserId = model.Id,
                Remark = "新增用户",
                IP = "",
                CreateTime = DateTime.Now
            });

            return new SuccessResult();
        }
        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result UpdateUser(UpdateUserRequest request)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var repositoryUserOperateLog = _unitOfwork.GetRepository<SysUserOperateLog>();

            var checkModel = repositorySysUser.TableNoTracking.SingleOrDefault(p => p.UserName == request.UserName && p.IsDelete == false);
            if (checkModel != null && checkModel.Id != request.Id)
            {
                return new FailResult("已存在相同用户名");
            }

            //管理员不能修改
            if (repositorySysUser.TableNoTracking.Any(p => p.UserName == "admin" && p.IsDelete == false && p.Id == request.Id))
            {
                return new FailResult("admin不能修改");
            }

            var model= repositorySysUser.TableNoTracking.SingleOrDefault(p => p.Id == request.Id && p.IsDelete == false);
            if (model == null)
            {
                return new FailResult("找不到用户数据，请刷新后重试");
            }
            model.UserName = request.UserName;
            model.TrueName = request.TrueName;
            model.Sex = request.Sex;
            model.Phone = request.Phone;
            model.Email = request.Email;
            model.DeptId = request.DeptId;
            model.UpdateId = request.OpeatorId;
            model.UpdateTime = DateTime.Now;
            repositorySysUser.Update(model);

            //日志
            repositoryUserOperateLog.Insert(new SysUserOperateLog
            {
                OperateId = request.OpeatorId,
                OperateType = 1,
                UserId = model.Id,
                Remark = "修改用户",
                IP = "",
                CreateTime = DateTime.Now
            });

            return new SuccessResult();
        }
        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="opeatorId"></param>
        /// <returns></returns>
        public Result DeleteUser(int userId, int opeatorId)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var repositoryUserOperateLog = _unitOfwork.GetRepository<SysUserOperateLog>();
            var model = repositorySysUser.Table.SingleOrDefault(p => p.Id == userId);

            //管理员不能删除
            if (repositorySysUser.TableNoTracking.Any(p => p.UserName == "admin" && p.IsDelete == false && p.Id == userId))
            {
                return new FailResult("admin不能删除");
            }

            model.IsDelete = true;
            model.UpdateId = opeatorId;
            model.UpdateTime = DateTime.Now;
            _unitOfwork.Save();

            //日志
            repositoryUserOperateLog.Insert(new SysUserOperateLog
            {
                OperateId = opeatorId,
                OperateType = 2,
                UserId = model.Id,
                Remark = "删除用户",
                IP = "",
                CreateTime = DateTime.Now
            });

            return new SuccessResult();
        }
        /// <summary>
        /// 启用用户
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="opeatorId"></param>
        /// <returns></returns>
        public Result EnableUser(int userId, int opeatorId)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var repositoryUserOperateLog = _unitOfwork.GetRepository<SysUserOperateLog>();
            var model = repositorySysUser.Table.SingleOrDefault(p => p.Id == userId);
            if (model == null)
            {
                return new FailResult("找不到用户数据，请刷新后重试");
            }
            if (model.Status != 1)
            {
                return new FailResult("该用户状态不为禁用，请刷新后重试");
            }

            model.Status = 0;
            model.UpdateId = opeatorId;
            model.UpdateTime = DateTime.Now;
            _unitOfwork.Save();

            //日志
            repositoryUserOperateLog.Insert(new SysUserOperateLog
            {
                OperateId = opeatorId,
                OperateType = 3,
                UserId = model.Id,
                Remark = "启用用户",
                IP = "",
                CreateTime = DateTime.Now
            });

            return new SuccessResult();
        }
        /// <summary>
        /// 禁用用户
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="opeatorId"></param>
        /// <returns></returns>
        public Result DisableUser(int userId, int opeatorId)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var repositoryUserOperateLog = _unitOfwork.GetRepository<SysUserOperateLog>();
            var model = repositorySysUser.Table.SingleOrDefault(p => p.Id == userId);
            if (model == null)
            {
                return new FailResult("找不到用户数据，请刷新后重试");
            }
            if (model.Status != 0)
            {
                return new FailResult("该用户状态不为启用，请刷新后重试");
            }

            model.Status = 1;
            model.UpdateId = opeatorId;
            model.UpdateTime = DateTime.Now;
            _unitOfwork.Save();

            //日志
            repositoryUserOperateLog.Insert(new SysUserOperateLog
            {
                OperateId = opeatorId,
                OperateType = 4,
                UserId = model.Id,
                Remark = "禁用用户",
                IP = "",
                CreateTime = DateTime.Now
            });

            return new SuccessResult();
        }
        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result RetsetPassword(RetsetPasswordRequest request)
        {
            var repositorySysUser = _unitOfwork.GetRepository<SysUser>();
            var repositoryUserOperateLog = _unitOfwork.GetRepository<SysUserOperateLog>();
            var model = repositorySysUser.Table.SingleOrDefault(p => p.Id == request.UserId);
            if (model == null)
            {
                return new FailResult("找不到用户数据，请刷新后重试");
            }

            model.Password = request.Password;
            model.UpdateId = request.OpeatorId;
            model.UpdateTime = DateTime.Now;
            _unitOfwork.Save();

            //日志
            repositoryUserOperateLog.Insert(new SysUserOperateLog
            {
                OperateId = request.OpeatorId,
                OperateType = 5,
                UserId = model.Id,
                Remark = "重置密码",
                IP = "",
                CreateTime = DateTime.Now
            });

            return new SuccessResult();
        }

        /// <summary>
        /// 获取用户分配的角色
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public GetUserRoleResponse GetUserRole(int userId)
        {
            GetUserRoleResponse result = new GetUserRoleResponse();
            result.Id = userId;

            //分配的角色
            var repositoryRole = _unitOfwork.GetRepository<SysRole>();
            var repositoryUserRoleMap = _unitOfwork.GetRepository<SysUserRoleMap>();
            var query = from a in repositoryRole.TableNoTracking
                        join b in repositoryUserRoleMap.TableNoTracking.Where(p => p.UserId == userId) on a.Id equals b.RoleId into tmpB
                        from b in tmpB.DefaultIfEmpty()
                        where a.IsDelete == false
                        select new UserRoleModel
                        {
                            Id = a.Id,
                            RoleName = a.RoleName,
                            ParentId = 0,
                            //SortIndex = a.SortIndex,
                            IsAssign = (b != null)
                        };
            var roleRoles = query.ToList();
            result.UserRoles = roleRoles;

            return result;
        }

        /// <summary>
        /// 分配角色
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result AssignUserRole(AssignUserRoleRequest request)
        {
            var repositoryUserRoleMap = _unitOfwork.GetRepository<SysUserRoleMap>();

            //开启事务
            using (TransactionScope scope = new TransactionScope())
            {
                //删除旧的分配模块
                _unitOfwork.ExecuteSqlCommand($"delete from Sys_UserRoleMap where UserId={request.Id}");

                //角色分配模块
                foreach (var li in request.AssignRoles)
                {
                    repositoryUserRoleMap.Insert(new SysUserRoleMap
                    {
                        RoleId = li,
                        UserId = request.Id,
                        CreateId = request.OpeatorId,
                        CreateTime = DateTime.Now,
                    });
                }

                //提交事务
                scope.Complete();
            }

            return new SuccessResult();
        }

        /// <summary>
        /// 获取用户分配的模块
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public GetUserModuleResponse GetUserModule(int userId)
        {
            GetUserModuleResponse result = new GetUserModuleResponse();
            result.Id = userId;

            //分配的模块
            var repositoryModule = _unitOfwork.GetRepository<SysModule>();
            var repositoryUserModuleMap = _unitOfwork.GetRepository<SysUserModuleMap>();
            var query = from a in repositoryModule.TableNoTracking
                        join b in repositoryUserModuleMap.TableNoTracking.Where(p => p.UserId == userId) on a.Id equals b.ModuleId into tmpB
                        from b in tmpB.DefaultIfEmpty()
                        where a.IsDelete == false
                        orderby a.SortIndex
                        select new UserModuleModel
                        {
                            Id = a.Id,
                            ModuleName = a.ModuleName,
                            ModuleCode = a.ModuleCode,
                            ParentId = a.ParentId,
                            SortIndex = a.SortIndex,
                            IsAssign = (b != null)
                        };
            var roleModules = query.ToList();
            var roleModulesNew = query.ToList();
            foreach (var li in roleModulesNew)
            {
                //有子节点，设置IsAssign为false，防止tree重复勾选
                if (roleModules.Any(p => p.ParentId == li.Id))
                {
                    li.IsAssign = false;
                }
            }
            result.UserModules = roleModulesNew;

            return result;
        }

        /// <summary>
        /// 分配模块
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result AssignUserModule(AssignUserModuleRequest request)
        {
            var repositoryUserModuleMap = _unitOfwork.GetRepository<SysUserModuleMap>();

            //开启事务
            using (TransactionScope scope = new TransactionScope())
            {
                //删除旧的分配模块
                _unitOfwork.ExecuteSqlCommand($"delete from Sys_UserModuleMap where UserId={request.Id}");

                //角色分配模块
                foreach (var li in request.AssignModules)
                {
                    repositoryUserModuleMap.Insert(new SysUserModuleMap
                    {
                        ModuleId = li,
                        UserId = request.Id,
                        CreateId = request.OpeatorId,
                        CreateTime = DateTime.Now,
                    });
                }

                //提交事务
                scope.Complete();
            }

            return new SuccessResult();
        }

        /// <summary>
        /// 获取所有模块列表
        /// </summary>
        /// <returns></returns>
        public IList<GetModuleListModel> GetUserMenu(int userId)
        {
            var repositoryModule = _unitOfwork.GetRepository<SysModule>();
            var repositoryUserModuleMap = _unitOfwork.GetRepository<SysUserModuleMap>();
            var repositoryRole = _unitOfwork.GetRepository<SysRole>();
            var repositoryUserRoleMap = _unitOfwork.GetRepository<SysUserRoleMap>();
            var repositoryRoleModuleMap = _unitOfwork.GetRepository<SysRoleModuleMap>();

            #region 管理员角色具有所有权限
            var queryAdmin = from a in repositoryUserRoleMap.TableNoTracking
                             join b in repositoryRole.TableNoTracking on a.RoleId equals b.Id
                             where a.UserId == userId
                             && b.RoleName == "管理员"
                             && b.IsDelete == false
                             select a;
            if (queryAdmin.Any())
            {
                return _moduleService.GetAllModuleList();
            } 
            #endregion

            //分配的模块
            var query = from a in repositoryUserModuleMap.TableNoTracking
                        join b in repositoryModule.TableNoTracking on a.ModuleId equals b.Id
                        where b.IsDelete == false
                        && b.IsMenu == true
                        && a.UserId == userId
                        select new GetModuleListModel
                        {
                            Id = b.Id,
                            ModuleName = b.ModuleName,
                            ModuleCode = b.ModuleCode,
                            ParentId = b.ParentId,
                            SortIndex = b.SortIndex,
                            MenuPath = b.MenuPath,
                            Icon = b.Icon,
                        };
            var list = query.ToList();

            //所属角色下的菜单
            
            var query2 = from a in repositoryUserRoleMap.TableNoTracking
                         join b in repositoryRole.TableNoTracking on a.RoleId equals b.Id
                         join c in repositoryRoleModuleMap.TableNoTracking on a.RoleId equals c.RoleId
                         join d in repositoryModule.TableNoTracking on c.ModuleId equals d.Id
                         where a.UserId == userId
                         && b.IsDelete == false
                         && d.IsDelete == false
                         && d.IsMenu == true
                         select new GetModuleListModel
                         {
                             Id = d.Id,
                             ModuleName = d.ModuleName,
                             ModuleCode = d.ModuleCode,
                             ParentId = d.ParentId,
                             SortIndex = d.SortIndex,
                             MenuPath = d.MenuPath,
                             Icon = d.Icon,
                         };
            var list2 = query2.ToList();
            var listNew = list2.Where(p => list.Any(p2 => p2.Id == p.Id) == false).ToList();
            list.AddRange(listNew);
            return list;
        }

        /// <summary>
        /// 记录登录日志
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Result LogLogin(LogLoginRequest request)
        {
            var repositorySysUserLoginLog = _unitOfwork.GetRepository<SysUserLoginLog>();
            repositorySysUserLoginLog.Insert(new SysUserLoginLog
            {
                UserName = request.UserName,
                UserId = request.UserId,
                IP = request.IP,
                UserAgent = request.UserAgent,
                LoginStatus = request.LoginStatus,
                LoginTime = DateTime.Now
            });
            _unitOfwork.Save();
            return new SuccessResult();
        }
    }

}
